#include <cstdlib>
#include <iostream>
#include <fstream>
#include <time.h>
#include <stdio.h>
#include <string.h>
#include "Archivo.h"


#define LONGITUDDEBUFFERCONFECHA 100 //renglon completo a escribir en el archivo
#define LONGITUDFECHA 24             //cantidad de caracteres que utiliza el string de fecha para componerse
/*#define MENUDEOPCIONES "Ingrese una de las siguientes opciones para continuar:\n1-Escribir\n2-Leer Todo
\n3-Buscar por palabra\n4-Buscar por fechas\n0-Salir\n\nOpcion Numero:"
#define SALIR 0; si se modifica el menu esto puede tener que modificarse*/
#define CANTIDADLINEASAIMPRIMIRPORPANTALLA 15
#define MAXLONGARCHIVO 1000 //para probar se hizo corto

using namespace std;


/*pedir un enter para pausas*/
void pedirEnter(int contador)
{
	char pausa[1];
	if ((contador%CANTIDADLINEASAIMPRIMIRPORPANTALLA)==0) 
    {
    printf("Presione enter para seguir...");
    cin >> pausa[0] ;
    }
}





//*****************************************************************************
/* obtenerNumArchivo, obtiene un entero desde un archivo de configuracion
 * que el el numero de archivo que actualmente esta usando el logguer.
 * */
int Archivo::obtenerNumArchivoLog()
{	//toma el numero que hay en conflog.txt
	string line;
    ifstream myfile ("conflog.txt");
  	if (myfile.is_open())
    	{
      		getline (myfile,line);
      		//cout << line << endl;
			myfile.close();
  			return atoi (&line[0]);
    	}
	return -1;//codigo de error, por ejemplo que lo ubiesen borrado o cambiado
}






//*****************************************************************************
/* convertirNombreDeArchivo crea dinamicamente los nombre de archivo para ejecutar las 
 * funciones aplicadas a todos los archivos
 * */
string Archivo::convertirNombreDeArchivo(string nomArchivo,int numFile,string extension)
{
	string numenstr,retorno;
	retorno.append(&nomArchivo[0]);
	memset(&numenstr[0], 0, sizeof(numenstr));
	sprintf(&numenstr[0], "%d", numFile);
	retorno.append(&numenstr[0]);
	retorno.append(&extension[0]);
	return retorno;
}






//*****************************************************************************
/* encontraPalabra devuelve true si la palabra esta contenida en la oracion
 * */

bool encontrarPalabra(char oracion[],char palabra[])
{
	bool resultado=false;
	int x=0;/*posOracion*/ int y=0; //posPalabra
	string palabrastr=&palabra[0];
	if (palabrastr.size()==0) return resultado;
	y=0;//solo para quitar error de y no usada
	while (!((oracion[x]=='\n')||(oracion[x]=='\0')||resultado))
	//resultado->mientras que no haya encontrado recoro la oracion
	//(oracion[x]=='\n')||(oracion[x]=='\0') verif fin de oracion
	{
		if (oracion[x]==palabra[y]) 
		{
			if ((y+1)==((int)palabrastr.size())) resultado=true;
			y++;
		}
		else y=0;
		x++;
	};
	return resultado;
}





//*****************************************************************************
/* lookForWord recibe un archivo y pide un palabra y muestra por pantalla
 * todos los renglones que contengan la palabra ingresada
 * */
void lookForWord(string nomArchivo,string palabra)
{
	FILE * pFile;
	pFile = fopen (&nomArchivo[0] , "r");
	char buffer [LONGITUDDEBUFFERCONFECHA]; //buffer de lectura
	bool finDeArchivo=true; //logica inversa false >> fin de archivo
	int contador=0;//para las impresiones por pantalla que en caso de ser muchas necesitan una pausa
	//string query;//palabra a consultar en el archivo
	//code part
	/*cout << "Letras a buscar (distingue mayusculas) :";
	cin >> query;*/
	if (pFile == NULL) perror ("Error opening file");//control
	else
	     {
         while (finDeArchivo)
         {
		 pedirEnter(contador);
         string strbuffer;
         fgets (&strbuffer[0]  ,LONGITUDDEBUFFERCONFECHA, pFile);
         strncpy (buffer,&strbuffer[0],LONGITUDDEBUFFERCONFECHA);
         if ( feof (pFile) ) finDeArchivo=false;
         else {   
         		bool encontrado=encontrarPalabra(&strbuffer[0],&palabra[0]);          
				if(encontrado)
				{
					try 
					{
         				contador=contador+1;
						finDeArchivo=true;//para aclarar codigo
              			fputs (buffer , stdout);
              		}
              		catch(exception e){
                	}
              	}
              };
         };
     fclose (pFile);
     }
}







//*****************************************************************************
/* lookForWord recibe un archivo y pide un palabra y muestra por pantalla
 * todos los renglones que contengan la palabra ingresada
 * */
void lookForWord(string nomArchivo,string palabra,int* pausaDeImpresion)
{
	FILE * pFile;
	pFile = fopen (&nomArchivo[0] , "r");
	char buffer [LONGITUDDEBUFFERCONFECHA]; //buffer de lectura
	bool finDeArchivo=true; //logica inversa false >> fin de archivo
	int contador=(*pausaDeImpresion);//para las impresiones por pantalla que en caso de ser muchas necesitan una pausa
	//string query;//palabra a consultar en el archivo
	//code part
	/*cout << "Letras a buscar (distingue mayusculas) :";
	cin >> query;*/
	if (pFile == NULL) perror ("Error opening file");//control
	else
	     {
         while (finDeArchivo)
         {
		 pedirEnter(contador);
         string strbuffer;
         fgets (&strbuffer[0]  ,LONGITUDDEBUFFERCONFECHA, pFile);
         strncpy (buffer,&strbuffer[0],LONGITUDDEBUFFERCONFECHA);
         if ( feof (pFile) ) finDeArchivo=false;
         else {   
         		bool encontrado=encontrarPalabra(&strbuffer[0],&palabra[0]);          
				if(encontrado)
				{
					try 
					{
         				contador++;
						finDeArchivo=true;//para aclarar codigo
              			fputs (buffer , stdout);
              		}
              		catch(exception e){
                	}
              	}
              };
         };
     fclose (pFile);
     }
     (*pausaDeImpresion)=contador;
}









/********************************************************
**************FUNCION PONER EN ARCHIVO SIN PARAMETROS****
*******************************************************
* Pone en este archivo una linea que pide por stdin*/

void Archivo::putInFile(char * archivo)
{
  //escribir
  string str;
  cout << "Linea a guardar: ";
  cin >> str;
  Archivo file;
  file.putInFile(archivo,str);
};
void Archivo::putInFile(char* archivo,string str)     
{
  ofstream myfile;
  myfile.open (archivo,ios::app);
  
  //este parrafo levanta la hora del sistema en un tipo char*
  time_t rawtime2;
  struct tm * timeinfo2;
  time ( &rawtime2 );
  timeinfo2 = localtime ( &rawtime2 );
  char* hora=asctime (timeinfo2);
  //este parrafito es para sacarle el /n del final a la hora
  char hora2[LONGITUDFECHA];
  strncpy (hora2,hora,LONGITUDFECHA);
  
  myfile << hora2 << "  " << str;
  myfile << "\n";
  //cada vez que realizo un escritura si pase el maximo seteo el 
  //CAMBIO DE NOMBRE
  if (myfile.tellp()>MAXLONGARCHIVO)//tell que controla la posicion
  {
  	Archivo file;
  	int numArchivo=file.obtenerNumArchivoLog();
  	ofstream CONF;
  	CONF.open("conflog.txt");
  	CONF.seekp ( 0 );//voy a sobreescribir al principio
  	CONF << numArchivo+1 << "\n";  	
  	//modificar el archivo de configuraciones
  };
  myfile.close();
}

/********************************************************
*****************FUNCION LEER DE ARCHIVO *****************
*******************************************************
* Funcion para el help; muestra completamente un archivo por pantalla*/

void Archivo::getOutFile(string nomArchivo)
{
     bool finDeArchivo=true; //logica inversa false >> fin de archivo
     int contador=1;
     FILE * pFile;
     char buffer [LONGITUDDEBUFFERCONFECHA];
     pFile = fopen (&nomArchivo[0] , "r");
     if (pFile == NULL) perror ("Error opening file");
     else
     {
         while (finDeArchivo) {
 		 pedirEnter(contador);
         fgets (buffer  ,LONGITUDDEBUFFERCONFECHA, pFile);
         /*Esta condicion se encuentra porque al final del archivo hay una linea en blanco
         y me ocurria que por esa linea me imprimia 2 veces la ultima linea porque las funciones
         ponen automaticamente el cursor en el proximo renglon y feof verifica el proximo renglon, 
         y NO DOS MAS ABAJO*/
         if ( feof (pFile) ) finDeArchivo=false;
         else {              
              try {
         		contador=contador+1;
              	finDeArchivo=true;
              	fputs (buffer , stdout);
              	}
              catch(exception e){
                }
              };
         };
     fclose (pFile);
     }
};

/********************************************************
*****************FUNCION LEER DE ARCHIVO *****************
*******************************************************
* Funcion para la lectura de multiples archivos simultaneamente
* ESPECIAL PARA MULTIPLES ARCHIVOS*/
void Archivo::getOutFile(string nomArchivo,int* lineasImpresas)
{
     bool finDeArchivo=true; //logica inversa false >> fin de archivo
     int contador=(*lineasImpresas);
     FILE * pFile;
     char buffer [LONGITUDDEBUFFERCONFECHA];
     pFile = fopen (&nomArchivo[0] , "r");
     if (pFile == NULL) perror ("Error opening file");
     else
     {
          while (finDeArchivo) {
		 pedirEnter(contador);
         fgets (buffer  ,LONGITUDDEBUFFERCONFECHA, pFile);
         /*Esta condicion se encuentra porque al final del archivo hay una linea en blanco
         y me ocurria que por esa linea me imprimia 2 veces la ultima linea porque las funciones
         ponen automaticamente el cursor en el proximo renglon y feof verifica el proximo renglon, 
         y NO DOS MAS ABAJO*/
         if ( feof (pFile) ) finDeArchivo=false;
         else {              
              try {
               	contador=contador+1;
              	finDeArchivo=true;
              	fputs (buffer , stdout);
              	}
              catch(exception e){
                }
              };
         };
     fclose (pFile);
     }
     (*lineasImpresas)=contador;
};







//*****************************************************************************
/* lookForDate tiene una fecha dada, y la busca en ese archivo, mostrando
 * por pantalla los registros ingresados ese dia.
 * */
void lookForDate(string nomArchivo,string dia,string mes, string anio){
     char buffer [LONGITUDDEBUFFERCONFECHA]={'\0'};
/*	 string strdia="dd";//ver nota
	 string strmes="mm";//ver nota
	 string stranio="aaaa";//ver nota
	 */
	 /* Parece innecesario definir inicalmente los strings pero ocurria que los apilaba en el mismo lugar
	  * y dejaba basura en todos si no estaban estas declaraciones iniciales y es el problema de porque
	  * otras funciones no tienen declarados parametros en su cabezera porque no encontraba la forma de 
	  * hacer que reconociera correctamente los char*!!!!!!!!!!*/
	 char endline='\n';
/*	 strdia=convertirNombreDeArchivo((string)dia,&endline);
	 strmes=convertirNombreDeArchivo((string)mes,&endline);
	 stranio=convertirNombreDeArchivo((string)anio,&endline);*/
     /*strncpy (&strdia[0],dia,2);
     strncpy (&strdia[2],&endline,1);
     strncpy (buffer,&strdia[0],3);//control
     strncpy (&strmes[0],mes,3);
     strncpy (&strmes[3],&endline,1);
     strncpy (buffer,&strmes[0],4);//control
     strncpy (&stranio[0],anio,4);
     strncpy (&stranio[4],&endline,1);
     strncpy (buffer,&stranio[0],5);//control*/
     bool finDeArchivo=true; //logica inversa false >> fin de archivo
     int contador=1;
     FILE * pFile2;
     bool encontrado=false;//para evitar recorridos innecesarios

     pFile2 = fopen (&nomArchivo[0] , "r");
     if (pFile2 == NULL) perror ("Error opening file");
     else
     {
         while ((finDeArchivo)||(feof (pFile2))) 
         {
         	
		 	pedirEnter(contador);
         	string strbuffer;
         	fgets (&strbuffer[0],LONGITUDFECHA+1, pFile2);
         	//CUANDO CORTO STRBUFFER TENGOP QUE PONER UN \0 O \N AL FINAL PARA QUE SIGA SIENDO STRING
         	strncpy (&strbuffer[0]+LONGITUDFECHA+1,&endline,1);
         	strncpy (buffer,&strbuffer[0],LONGITUDFECHA+4);
         	/*Esta condicion se encuentra porque al final del archivo hay una linea en blanco
         	y me ocurria que por esa linea me imprimia 2 veces la ultima linea porque las funciones
         	ponen automaticamente el cursor en el proximo renglon y feof verifica el proximo renglon, 
         	y NO DOS MAS ABAJO*/
         	if ( feof (pFile2) ) finDeArchivo=false;//esta linea es innecesaria
         	else {   
         			//string strquery;
         			//strncpy (&strquery[0],&query[0],strlen(query));
         			
         			bool encontrado1=encontrarPalabra(&strbuffer[0],&dia[0]);//es es dia?
         			bool encontrado2=encontrarPalabra(&strbuffer[0],&mes[0]);//es esa mes?
         			bool encontrado3=encontrarPalabra(&strbuffer[0],&anio[0]);//es ese anio?
         			
					if( encontrado1 && encontrado2 && encontrado3 )
					{
						try 
						{
							encontrado=true;
        	      			fputs (&strbuffer[0] , stdout);	printf("  ");
        	      			fgets (&strbuffer[0],LONGITUDDEBUFFERCONFECHA, pFile2);//termino de ver la linea
        	      			fputs (&strbuffer[0] , stdout); 
        	      			contador=contador+1;
						}
        	      		catch(exception e){
       	         		}
       	         	
					}
       	         	else 
       	         	{
       	         		fgets (&strbuffer[0],LONGITUDDEBUFFERCONFECHA, pFile2);//termino de ver la linea
       	         		if ((encontrado)&&(contador!=1)) finDeArchivo=false;//para evitar buscar luego de haber encontrado la fecha
       	         	};//end if encontrado123
       	    };//end else feof pfile
         };//end while fin de archivo
     fclose (pFile2);
     }//end else      if (pFile == NULL)
}//end look for date








//*****************************************************************************
/* lookForDate tiene una fecha dada, y la busca en ese archivo, mostrando
 * por pantalla los registros ingresados ese dia.ESPECIAL PARA MULTIPLES ARCHIVOS
 * */
void lookForDate(string nomArchivo,string dia,string mes, string anio,int* pausaDeImpresion){
     char buffer [LONGITUDDEBUFFERCONFECHA]={'\0'};
	 string strdia;//ver nota
	 string strmes="mm";//ver nota
	 string stranio="aaaa";//ver nota
	 /* Parece innecesario definir inicalmente los strings pero ocurria que los apilaba en el mismo lugar
	  * y dejaba basura en todos si no estaban estas declaraciones iniciales y es el problema de porque
	  * otras funciones no tienen declarados parametros en su cabezera porque no encontraba la forma de 
	  * hacer que reconociera correctamente los char*!!!!!!!!!!*/
	 char endline='\n';
/*	 strdia=convertirNombreDeArchivo((string)dia,&endline);
	 strmes=convertirNombreDeArchivo((string)mes,&endline);
	 stranio=convertirNombreDeArchivo((string)anio,&endline);*/
/*   strncpy (&strdia[0],dia,2);
     strncpy (&strdia[2],&endline,1);
     strncpy (buffer,&strdia[0],3);//control
     strncpy (&strmes[0],mes,3);
     strncpy (&strmes[3],&endline,1);
     strncpy (buffer,&strmes[0],4);//control
     strncpy (&stranio[0],anio,4);
     strncpy (&stranio[4],&endline,1);
     strncpy (buffer,&stranio[0],5);//control	*/
     bool finDeArchivo=true; //logica inversa false >> fin de archivo
     int contador=(*pausaDeImpresion);
     FILE * pFile2;
     bool encontrado=false;//para evitar recorridos innecesarios

     pFile2 = fopen (&nomArchivo[0] , "r");
     if (pFile2 == NULL) perror ("Error opening file");
     else
     {
         while ((finDeArchivo)&&(!(feof (pFile2)))) 
         {
         	
		 	pedirEnter(contador);
         	string strbuffer;
         	fgets (&strbuffer[0],LONGITUDFECHA+1, pFile2);
         	//CUANDO CORTO STRBUFFER TENGOP QUE PONER UN \0 O \N AL FINAL PARA QUE SIGA SIENDO STRING
         	strncpy (&strbuffer[0]+LONGITUDFECHA+1,&endline,1);
         	strncpy (buffer,&strbuffer[0],LONGITUDFECHA+4);
         	/*Esta condicion se encuentra porque al final del archivo hay una linea en blanco
         	y me ocurria que por esa linea me imprimia 2 veces la ultima linea porque las funciones
         	ponen automaticamente el cursor en el proximo renglon y feof verifica el proximo renglon, 
         	y NO DOS MAS ABAJO*/
         	if ( feof (pFile2) ) finDeArchivo=false;//esta linea es innecesaria
         	else {   
         			//string strquery;
         			//strncpy (&strquery[0],&query[0],strlen(query));
         			//strdia=strbuffer.substr(8,2);
         			strdia=string(&strbuffer[0],8,2);
         			bool encontrado1=encontrarPalabra(&strdia[0],&dia[0]);//es es dia?
         			bool encontrado2=encontrarPalabra(&strbuffer[0],&mes[0]);//es esa mes?
         			bool encontrado3=encontrarPalabra(&strbuffer[0],&anio[0]);//es ese anio?
         			
					if( encontrado1 && encontrado2 && encontrado3 )
					{
						try 
						{
							encontrado=true;
							//cout << strdia << endl;
        	      			fputs (&strbuffer[0] , stdout);printf("  ");
        	      			fgets (&strbuffer[0],LONGITUDDEBUFFERCONFECHA, pFile2);//termino de ver la linea
        	      			fputs (&strbuffer[0] , stdout);
        	      			contador=contador+1;
						}
        	      		catch(exception e){
       	         		}
					
       	         	
					}
       	         	else 
       	         	{
       	         		fgets (&strbuffer[0],LONGITUDDEBUFFERCONFECHA, pFile2);//termino de ver la linea
       	         		if ((encontrado)&&(contador!=1)) finDeArchivo=false;//para evitar buscar luego de haber encontrado la fecha
       	         	};//end if encontrado123
       	    };//end else feof pfile
         };//end while fin de archivo
     fclose (pFile2);
     }//end else      if (pFile == NULL)
     (*pausaDeImpresion)=contador;
}//end look for date












//*****************************************************************************
/* lookForFile-palabra rellama a lookForWord y lookfordate aplicandolos a cada archivo existente.
 * */
void Archivo::lookForFile(int numArchivoActivo,char modo)
{
	int numFile=0;
	string nombreArchivo="Logguer";
	string extension=".txt";
	
	string palabra;//palabra a consultar en el archivo		
	string anio="aaaa";
    string dia="dd";
    string mes="mm";
    string meses[12] ={"Jan","Feb","Mar","Apr","May","Jun","Jul","Ago","Set","Oct","Nov","Dic"};
	
	//string numenstr;
	string nomArchivo=nombreArchivo;
	
	switch (modo){
	case 'B':{	cout << "Letras a buscar (distingue mayusculas) :";
				cin >> palabra;	break;	
			}
	case 'F':		
			{
   				retorno01:
   				cout << "Ingrese dia (dd): \0";	 		cin >> dia;
   		    	cout << "Ingrese mes (mm): \0";			cin >> mes;
        		cout << "Ingrese anio (aaaa): \0";		cin >> anio;
        		//si no es fecha valida en esta linea vuelvo a pedirlas, anio no valido a partir de 2015
        		if 	(
	        		(atoi (&dia[0])<1)		||	(atoi (&dia[0])>31)		||
		           	(atoi (&mes[0])<1)		||	(atoi (&mes[0])>12)				||
		           	(atoi (&anio[0])<1901)	||	((atoi (&anio[0]))>2015)	
		           	) goto retorno01;
		    	break;	
			}
	case 'M':{	cout << "Mostrando resultados:";	break;	}
	default: {	return;	}
	};
	int pausaDeImpresion=1;
	do
	{
		nomArchivo=convertirNombreDeArchivo(nombreArchivo,numFile,extension);		//concatenar el nombre del archivo
		if (modo=='B')	{	lookForWord(nomArchivo,palabra,&pausaDeImpresion);}		
		if (modo=='F')	{   lookForDate(nomArchivo,dia,meses[atoi (&mes[0])-1],anio,&pausaDeImpresion);}
		if (modo=='M')	{  	Archivo file;
							file.getOutFile(nomArchivo,&pausaDeImpresion);}
		numFile++;
	}while(numFile<=numArchivoActivo);
};

